

package cn.liyao.web.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.liyao.im.util.ConversationUtil;
import cn.liyao.tool.annotation.RequireToken;
import cn.liyao.tool.api.R;
import cn.liyao.web.constant.ConversationType;
import cn.liyao.web.constant.FriendReqStatus;
import cn.liyao.web.constant.MessageTypeU;
import cn.liyao.web.constant.ReadStatus;
import cn.liyao.web.holder.CurrentUserIdHolder;
import cn.liyao.web.model.*;
import cn.liyao.web.repository.*;
import cn.liyao.web.vo.FriendVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import server.network.MBObserver;
import server.processor.OnlineProcessor;
import server.protocal.Protocal;
import server.protocal.ProtocalFactory;
import server.utils.LocalSendHelper;

import java.util.*;
import java.util.stream.Collectors;

@RestController
public class FriendController {

    private final FriendRepository friendRepository;

    private final UserRepository userRepository;

    private final FriendRecordRepository friendRecordRepository;

    private final MessageRepository messageRepository;

    private final OfflineMessageRepository offlineMessageRepository;

    private final ConversationUtil conversationUtil;

    private final ConversationRepository conversationRepository;

    @Autowired
    public FriendController(FriendRepository friendRepository, UserRepository userRepository, FriendRecordRepository friendRecordRepository,
                            MessageRepository messageRepository, OfflineMessageRepository offlineMessageRepository,ConversationUtil conversationUtil,
                            ConversationRepository conversationRepository

                            ) {
        this.friendRepository = friendRepository;
        this.userRepository = userRepository;
        this.friendRecordRepository = friendRecordRepository;
        this.messageRepository = messageRepository;
        this.offlineMessageRepository = offlineMessageRepository;
        this.conversationUtil = conversationUtil;
        this.conversationRepository = conversationRepository;
    }


    @PostMapping("/friend/handleRequest")
    @RequireToken()
    public R handleRequest(String recordId, Integer state) throws Exception {
        Optional<FriendRecord> friendRecordOpt = friendRecordRepository.findById(recordId);
        if (!friendRecordOpt.isPresent()) return R.fail("非法请求");

        FriendRecord friendRecord = friendRecordOpt.get();

        if (FriendReqStatus.fromValue(state) == FriendReqStatus.同意) {
            Friend friend = friendRepository.findFirstByUserIdAndFriendId(friendRecord.getReceiveId(),friendRecord.getSenderId());
            if(friend == null){
                friend = new Friend();
                friend.setAddTime(new Date());
                friend.setUserId(friendRecord.getReceiveId());
                friend.setFriendId(friendRecord.getSenderId());
                friend.setId(IdUtil.getSnowflakeNextIdStr());
            }else{
                friend.setState(0);
                friend.setAddTime(new Date());
            }
            friendRepository.save(friend);

            Friend friend1 = friendRepository.findFirstByUserIdAndFriendId(friendRecord.getSenderId(),friendRecord.getReceiveId());

            if(friend1 == null){
                friend1 = new Friend();
                friend1.setAddTime(new Date());
                friend1.setUserId(friendRecord.getSenderId());
                friend1.setFriendId(friendRecord.getReceiveId());
                friend1.setId(IdUtil.getSnowflakeNextIdStr());
            }else{
                friend1.setState(0);
                friend1.setAddTime(new Date());
            }
            friendRepository.save(friend1);


            friendRecord.setState(FriendReqStatus.同意.getValue());
            friendRecordRepository.save(friendRecord);




            String dataContent = JSONUtil.toJsonStr(friendRecord);
            Protocal p = ProtocalFactory.createCommonData(dataContent, "0", friendRecord.getSenderId(), true, null, MessageTypeU.VerifiedBy.getValue());
            Messages messages = new Messages();
            OfflineMessages offlineMessages = new OfflineMessages();
            BeanUtils.copyProperties(p, messages);
            BeanUtils.copyProperties(p, offlineMessages);
            messages.setFrom(friendRecord.getReceiveId());
            messageRepository.save(messages);





            // 深拷贝 这个对象
            JSONObject jsonObject =  JSONUtil.parseObj(messages);
            jsonObject.set("from",friendRecord.getReceiveId());
            conversationUtil.createMessageStatus(jsonObject.toBean(Messages.class));



            if (OnlineProcessor.isOnline(friendRecord.getSenderId())) {
                MBObserver resultObserver = new MBObserver() {
                    public void update(boolean sucess, Object extraObj) {
                        if (!sucess) {
                            offlineMessageRepository.save(offlineMessages);
                        }
                    }
                };
                LocalSendHelper.sendData(p, resultObserver);
                createConversation(friendRecord.getSenderId(),friendRecord.getReceiveId() ,messages);
            } else {
                offlineMessageRepository.save(offlineMessages);
                createConversation(friendRecord.getSenderId(),friendRecord.getReceiveId(),messages);

            }

            if (OnlineProcessor.isOnline(friendRecord.getReceiveId())) {
                // 向自己发送一条通过消息，前端加上会话记录
                p.setTo(friendRecord.getReceiveId());
                MBObserver resultObserver = new MBObserver() {
                    public void update(boolean sucess, Object extraObj) {
                        if (!sucess) {
                            offlineMessageRepository.save(offlineMessages);
                        }
                    }
                };
                LocalSendHelper.sendData(p, resultObserver);
                createConversation(friendRecord.getReceiveId(),friendRecord.getSenderId(),messages);
            } else {
                offlineMessageRepository.save(offlineMessages);
                createConversation(friendRecord.getReceiveId(),friendRecord.getSenderId(),messages);
            }




            return R.success("成功");
        } else if (FriendReqStatus.fromValue(state) == FriendReqStatus.拒绝) {
            friendRecord.setState(FriendReqStatus.拒绝.getValue());
            friendRecordRepository.save(friendRecord);
            return R.success("成功");
        } else if (FriendReqStatus.fromValue(state) == FriendReqStatus.忽略) {
            friendRecord.setState(FriendReqStatus.忽略.getValue());
            friendRecordRepository.save(friendRecord);
            return R.success("成功");
        }
        return R.fail("错误[state]");
    }



    private void createConversation(String targetId, String userId , Messages messages){
        Optional<User> user = userRepository.findById(targetId);
        Conversation conversation =  conversationRepository.findOneByUserIdAndTargetId(userId,targetId);
        if(conversation == null){
            conversation = new Conversation();
            conversation.setId(IdUtil.getSnowflakeNextIdStr());
            conversation.setTargetId(targetId);
            conversation.setUserId(userId);
            conversation.setTimestamp(System.currentTimeMillis());
            conversation.setLastMessage(JSONUtil.toJsonStr(messages));
            conversation.setUnreadCount(1);
            conversation.setTop(false);
            conversation.setDisturb(false);
            conversation.setType(ConversationType.Single.getValue());
            conversation.setUserName(user.get().getNickName());
            conversation.setPortrait(user.get().getUserPortrait());
        }else{
            conversation.setLastMessage(JSONUtil.toJsonStr(messages));
            conversation.setTimestamp(System.currentTimeMillis());
        }
        conversationRepository.save(conversation);
    }


    @PostMapping("/friend/add")
    @RequireToken()
        public R friendAdd(String friendId, String reason) throws Exception {
        String userId = CurrentUserIdHolder.getCurrentUser();
        Optional<User> user = userRepository.findById(friendId);

        if(friendId.equals(userId)){
            return R.fail("自己不能自己发送添加好友申请");
        }


        FriendRecord record =  friendRecordRepository.findOneBySenderIdAndReceiveIdAndState(userId,user.get().getUserId(),0);
        if(record != null){
            return R.success("成功");
        }


        // 构建实体
        FriendRecord friendRecord = new FriendRecord();
        friendRecord.setId(IdUtil.getSnowflakeNextIdStr());
        friendRecord.setSenderId(userId);
        friendRecord.setReceiveId(user.get().getUserId());
        friendRecord.setState(0);
        friendRecord.setCreateAt(new Date());
        friendRecord.setReason(reason);
        friendRecord = friendRecordRepository.save(friendRecord);
        friendRecordRepository.save(friendRecord);

        String dataContent = JSONUtil.toJsonStr(friendRecord);
        final Protocal p = ProtocalFactory.createCommonData(dataContent, "0", friendId, true, null, MessageTypeU.AddFriend.getValue());

        Messages messages = new Messages();
        OfflineMessages offlineMessages = new OfflineMessages();
        BeanUtils.copyProperties(p, messages);
        BeanUtils.copyProperties(p, offlineMessages);
        messages.setType(ConversationType.System.getValue());
        offlineMessages.setType(ConversationType.System.getValue());

        messageRepository.save(messages);
        if (OnlineProcessor.isOnline(friendId)) {
            MBObserver resultObserver = new MBObserver() {
                public void update(boolean sucess, Object extraObj) {
                    if (!sucess) {
                        offlineMessageRepository.save(offlineMessages);
                    }
                }
            };
            LocalSendHelper.sendData(p, resultObserver);

        } else {
            offlineMessageRepository.save(offlineMessages);
        }


        return R.success("成功");
    }


    @GetMapping("/friendList")
    @RequireToken()
    @CrossOrigin
    public R friendList() {
        String userId = CurrentUserIdHolder.getCurrentUser();
        List<Friend> friends = friendRepository.findAllByUserIdAndState(userId, 0);

        Set<String> friendIds = friends.stream()
                .map(Friend::getFriendId)
                .collect(Collectors.toSet());

        List<User> list = userRepository.findAllById(friendIds);

        List<FriendVO> results = new ArrayList<>();

        for(User user : list){
            FriendVO friendVO = new FriendVO();
            BeanUtils.copyProperties(user,friendVO);
            Friend friend = friends.stream().filter((item)-> item.getFriendId().equals(user.getUserId())).findFirst().get();
            friendVO.setRemark(friend.getRemark());
            friendVO.setAddTime(friend.getAddTime());
            friendVO.setGender(user.getGender().name());
            results.add(friendVO);
        }


        return R.data(results);
    }

}